#include"channel.h"
#include"log.h"
Channel::Channel(EventLoop *loop):m_loop(loop){

}

Channel::Channel(EventLoop *loop, int fd):m_loop(loop),m_fd(fd){

}

Channel::~Channel(){

}

int Channel::getFd(){
    return m_fd;
}

void Channel::setHolder(std::shared_ptr<HttpData> holder){
    m_holder=holder;
}

std::shared_ptr<HttpData> Channel::getHolder(){
    //weak_tpr::lock() creates a shared_ptr that manages the referenced object
    std::shared_ptr<HttpData> ret(m_holder.lock());
    return ret;
}

void Channel::handleRead(){
    if(m_readHandler){
        m_readHandler();
    }
}

void Channel::handleWrite(){
    if(m_writeHandler){
        m_writeHandler();
    }
}

//EPOLLET： 将 EPOLL设为边缘触发(Edge Triggered)模式（默认为水平触发）
//EPOLLONESHOT： 只监听一次事件，当监听完这次事件之后，如果还需要继续监听这个socket的话，需要再次把这个socket加入到EPOLL队列里

//EPOLLIN       连接到达；有数据来临；
//EPOLLOUT      有数据要写；             
//EPOLLPRI      表示对应的文件描述符有紧急的数据可读（这里应该表示有带外数据到来）；
//EPOLLERR      表示对应的文件描述符发生错误；
//EPOLLHUP      表示对应的文件描述符被挂断；
/*EPOLLRDHUP    有些系统检测不到，可以使用EPOLLIN，read返回0，删除掉事件，关闭close(fd);
                若可以检测到则表示对端已关闭*/ 
void Channel::handleError(int fd, int err_num, std::string short_msg){
    record()<<"handleError"<<fd<<"-"<<short_msg;
}

void Channel::handleConn(){
    if(m_connHandler){
        m_connHandler();
    }
}

void Channel::handleEvents(){
    m_events = 0;
    if ((m_revents & EPOLLHUP) && !(m_revents & EPOLLIN)) {
        m_events = 0;
        return;
    }
    if (m_revents & EPOLLERR) {
        if (m_errorHandler) m_errorHandler();
        m_events = 0;
        return;
    }
    if (m_revents & (EPOLLIN | EPOLLPRI | EPOLLRDHUP)) {
        handleRead();
    }
    if (m_revents & EPOLLOUT) {
        handleWrite();
    }
    handleConn();
}

void Channel::setRevents(uint32_t ev){
    m_revents=ev;
}

void Channel::setEvents(uint32_t ev){
    m_events=ev;
}

uint32_t& Channel::getEvents(){
    return m_events;
}

uint32_t Channel::getLastEvents(){
    return m_last_events;
}

//更新last_events, 同时判断last_events是否实际上发生改变
bool Channel::EqualAndUpdateLastEvents(){
    bool ret=(m_last_events==m_events);
    m_last_events=m_events;
    return ret;
}
